
/**
 * Kohive.controllers.HivesController
 * @extends ExtMVC.Controller
 * Listens to events on the hive controls, creates Hives as necessary
 */
Kohive.controllers.HivesController = function() {
	Kohive.controllers.HivesController.superclass.constructor.call(this, {
				viewsPackage	: Kohive.controllers.HivesController.views
			});

	var os = ExtMVC.OS.getOS();
	var controller = this;

	this.registerViews({
				'hiveSummary'		: Kohive.HiveSummary,
				'hiveOptions'		: Kohive.HiveOptions,
				'hivePanel'			: Kohive.views.hives.Index,
				'addHivePanel'		: Kohive.views.hives.New,
				'addIntroHivePanel'	: Kohive.views.hives.NewIntro
			});

	this.addEvents(
			/**
	 * @event beforehiveload
	 * Fires before a Hive is loaded.  Return false from any listener to cancel the load
	 * @param {Kohive.models.Hive} hive The Hive which wants to be loaded
	 */
			'beforehiveload',

			/**
			 * @event hiveload
			 * Fires once a Hive load is complete
			 * @param {Kohive.models.Hive} hive The Hive which has just been loaded
			 */
			'hiveload',

			/**
			 * @event beforecreatehive
			 * Fires before a new Hive object is saved.  Return false to cancel creation
			 * @param {Kohive.models.Hive} hive The hive about to be created
			 */
			'beforecreatehive',

			/**
			 * @event hivecreated
			 * Fires after successful creation of a new hive
			 * @param {Kohive.models.Hive} hive The newly created hive
			 */
			'hivecreated',

			/**
			 * @event createhivefailed
			 * Fires if creation of a new hive failed for any reason.
			 * Return false with a listener to provide your own handling of this event, otherwise
			 * it defaults to showing an error message to the user
			 * @param {Kohive.models.Hive} hive A Hive model object which could not be saved
			 */
			'createhivefailed'
	);

	// Add events to the hivePanel
	this.handleEvent(os.hivePanel, 'new', 'new', this);
	this.handleEvent(os.hiveOptions, 'accept', 'acceptHive', this);
	this.handleEvent(os.hiveOptions, 'destroy', 'destroyHive', this);

	this.initListeners();

	// Refresh the hivePanel when you create a hive
	this.on('hivecreated', function(membership) {
				if (!membership)
					return;

				// Set the isNew property to true so it animates
				membership.data.hive.isNew = true;

				// Add the hive to the hive panel
				var btn = os.getHivePanel().add(membership);
			}, this);

	/**
	 * @property hivePanelShown
	 * @type Boolean
	 * True if the hive panel has been already shown
	 */
	this.hivePanelShown = false;

	/**
	 * Displays the Add Hive panel, anchored above a specific Ext.Button.  Intended to be attached
	 * to the click event of the Add Hive button on the HivePanel.
	 * @action addHive
	 * @param {Ext.Button} btn The Ext.Button to align the Add Hive panel over.  This will probably
	 * always be the Add Hive button, sitting in the HivePanel.specials container
	 */
	this.registerAction('new', function(btn) {
				var btn = btn || os.hivePanel.newButton;

				// Get the add hive panel if it has already been rendered
				var v = this.getRunningView('addHivePanel');

				var offset = [0, -45];

				if (!v) {
					// not rendered yet. Render now and show + align on render
					v = this.renderView('addHivePanel', {
								hidden		: true,
								listeners	: {
									'render'	: {
										fn	: function() {
											var tempTask = new Ext.util.DelayedTask(
													function() {
														this.showHUD(offset);
													}, this
											);

											tempTask.delay(10);
										}
									}
								}
							}
					);

					// add save and cancel actions to the Add Hive Panel now that it has been created
					this.handleEvent(v, 'cancel', 'cancelAddHive', this);
					this.handleEvent(v, 'save', 'saveHive', this);
				} else {
					v.show();
				};
			}
	);

	/**
	* Displays the Add Hive panel, anchored above a specific Ext.Button.  Intended to be attached
	* to the click event of the Add Hive button on the HivePanel.
	* @action addHive
	* @param {Ext.Button} btn The Ext.Button to align the Add Hive panel over.  This will probably
	* always be the Add Hive button, sitting in the HivePanel.specials container
	*/
	this.registerAction('new_intro', function(btn) {
				var btn = btn || os.hivePanel.newButton;

				// Get the add hive panel if it has already been rendered
				var v = this.getRunningView('addIntroHivePanel');

				var offset = [0, -45];

				if (!v) {
					// not rendered yet. Render now and show + align on render
					v = this.renderView('addIntroHivePanel', {
								hidden		: true,
								listeners	: {
									'render'	: {
										fn	: function() {
											var tempTask = new Ext.util.DelayedTask(
													function() {
														this.showHUD(offset);
													}, this
											);

											tempTask.delay(10);
										}
									}
								}
							}
					);

					this.newIntro = true;
					this.newIntroView = v;

					// add save and cancel actions to the Add Hive Panel now that it has been created
					this.handleEvent(v, 'cancel', 'cancelAddIntroHive', this);
					this.handleEvent(v, 'save', 'saveHive', this);
				} else {
					v.show();
				};
			}
	);

	/**
	 * Hides the add hive panel
	 * @action cancelAddHive
	 * @param {Ext.Panel} addHivePanel The add hive panel which fired the event
	 */
	this.registerAction('cancelAddHive', function(addHivePanel) {
				addHivePanel.hide();
			});

	/**
	* Hides the add hive panel
	* @action cancelAddHive
	* @param {Ext.Panel} addHivePanel The add hive panel which fired the event
	*/
	this.registerAction('cancelAddIntroHive', function(addHivePanel) {
				addHivePanel.hide();
			});

	/**
	 * Attempts to create and save a new Hive based on the values of the addHivePanel form
	 * @action saveHive
	 * @param {Ext.FormPanel} addHivePanel The add hive panel containing the add hive form
	 */
	this.registerAction('saveHive', function(addHivePanel) {
		var hive = null;
		if (this.newIntro) {
			hive = new Kohive.models.Hive({
						level	: this.newIntroView.getLevel(),
						title	: this.newIntroView.getValue()
					});

			this.newIntro = false;
		} else {
			// pro
			hive = new Kohive.models.Hive({
						level	: 1,
						title	: Ext.getCmp('new_hive_title').getValue()
					});
		};

		if (this.fireEvent('beforecreatehive', hive)) {
			hive.save({
						success		: function(record, response) {
							Kohive.OS.loadSession();

							addHivePanel.onSuccess();

							// Get the data from the response and add it to the hive model
							var data = Ext.apply(record.data, Ext
											.decode(response.responseText));

							// Create a new membership with the hive data
							var membership = new Kohive.models.Membership(data);
							membership.firstHive = addHivePanel.firstHive === true;

							controller.fireEvent('hivecreated', membership);

							// //check if it is the firsthive, and if so, show the intro popup for inviting members
							if (addHivePanel.firstHive === true) {
								var tempTask = new Ext.util.DelayedTask(
										function() {
											var membersController = Kohive.OS
													.getController('members');
											membersController.fireAction('new',
													membersController, [null,
															true]
											);
										}, this
								);
								tempTask.delay(5000);
							};
						},
						failure		: function(modelObj, response) {
							// Get the data from the response and add it to the hive model
							var data = Ext.decode(response.responseText);

							controller.fireEvent('createhivefailed', hive);

							addHivePanel.onFailure(modelObj, data);
						},
						callback	: function() {
							addHivePanel.endSave();
						},
						scope		: this
					}
			);

			// Call the startSave method which will disable the form
			addHivePanel.startSave();
		};
	}
	);

	/**
	 * Refreshes the contents of the global Hive Panel.
	 * @action refresh
	 * @param {Ext.Panel} hivePanel The global Hive Panel object
	 */
	this.registerAction('refresh', function(extra) {
		var hivePanel = extra || os.getHivePanel();

		Kohive.models.Membership.findAll({
					url			: '/account/memberships',
					listeners	: {
						'load'	: {
							scope	: this,
							fn		: function(store, records) {
								var different = true;

								if (store.totalLength == 0) {
									ExtMVC.OS.getOS().hivePanel
											.positionHivePanel();
									this.fireAction('new_intro');
								};

								// Get the current hive and check if anything has changed
								var currentHive = os.getCurrentMemberships();
								if (currentHive) {
									different = controller.checkForDifferences(
											currentHive, store
									);
								};

								// Check if it is a different hive
								if (!different) {
									// Kohive.OS.setCurrentMemberships(store);
									return controller
											.fireEvent('refresh', this);
								};

								Kohive.OS.setCurrentMemberships(store);

								// first, remove any existing items
								if (hivePanel.items)
									hivePanel.items.each(function(item) {
												hivePanel.remove(item);
											}, this);

								// now add each Hive in turn, with a click listener on each
								for (var i = 0; i < records.length; i++) {
									var hive = records[i];
									var isNew = false;
									var currentHive = os.getCurrentHive()
											|| null;
									if (currentHive
											&& currentHive.data.id == hive.data.id) {
										isNew = true;
									};

									// Check if the personal_hive_id is set
									if (hive.data.personal_hive_id) {
										// var btn = hivePanel.add(hive, isNew);
										if (isNew)
											btn.toggle(true);

										// console.log(hive.data);
										// btn.on('click', function(button) {
										// controller.fireAction('loadHive', controller, [null, button]);
										// }, hivePanel);
									} else {
										var btn = hivePanel.add(hive);
										if (isNew)
											btn.toggle(true);
									};
								};

								// if a hive is not currently loaded but one is in the location hash, load that now
								if (Kohive.OS.getCurrentHive() == null)
									Kohive.OS.loadHiveFromUrl();

								// Fade in all the views if the hive panel isnt already shown (first refresh)
								if (!this.hivePanelShown) {
									hivePanel.fireEvent('showview', this);
									// os.getQuickAppsBar().fireEvent( 'showview', this);
									// os.getWidgetBar().showView('t', {
									// duration: 2,
									// easing: 'easeOut'
									// });

									this.hivePanelShown = true;
								};

								// console.log(ExtMVC.OS.getOS().hivePanel.scroller);
								// console.log(ExtMVC.OS.getOS().hivePanel.latest);

								// scroll the hive panel
								// if (ExtMVC.OS.getOS().hivePanel.scroller) {
								// ExtMVC.OS.getOS().hivePanel.scroll(0, true, true);
								// };

								// this.el.anchorTo(Ext.getBody(), 'b-b');
								controller.fireEvent('refresh', this);
							}
						}
					}
				}
		);
	}
	);

	/**
	 * Accepts a hive invitation
	 * @action acceptHive
	 * @param {Kohive.HiveOptions} options The hive options bar
	 */
	this.registerAction('acceptHive', function(options, membership) {
				try {
					if (!membership)
						var membership = options.btn.membership || null;
				} catch (e) {
				};

				// Check if the membership is null
				if (membership == null)
					return;

				// Set the state field to active
				var values = {
					"state"	: "active"
				};

				// Fire off the accept request method and override the success method
				membership.update(values, {
							success	: function() {
								controller.fireAction('refresh', this);
							},
							failure	: function() {
								Ext.Msg
										.alert(
												Ext.ux.Translator
														.translate('accept_hive'),
												'301:'
														+ Ext.ux.Translator
																.translate('something_wrong')
										);
							}
						}
				);
			}
	);

	/**
	 * Destroys/deletes a hive from the users hive list
	 * @action destroyHive
	 * @param {Kohive.HiveOptions} options The hive options bar
	 */
	this.registerAction('destroyHive', function(options, membership, abtn) {
		try {
			if (!membership)
				var membership = options.btn.membership || null;
		} catch (e) {
		};

		// Check if the membership is null
		if (membership == null)
			return;

		var isPending = false;
		if (membership.data.state == "pending")
			isPending = true;

		// Will destroy/cancel an invite to a membership/hive
		var destroyFn = function(btn) {
			if (btn == 'yes') {
				// Get the btn of the hive which is being deleted/left and get the .center child,
				// this is where the text for the hive name is kept, keep a copy of it if we ever need
				// to restore it (on failure). then add a pending class so it fades out + is unselectable
				// and change the text to deleting
				var btn = abtn || options.btn;
				var center = btn.el.child('.center');
				var text = center.dom.innerHTML;

				btn.addClass('x-pending');
				center.update(Ext.ux.Translator.translate((isPending)
						? 'declining'
						: 'leaving'));

				// Fire off the accept request method and override the success method
				membership.destroy({
					success	: function() {
						Kohive.OS.loadSession();
						btn.animateRemoveHive();

						if (membership.data.id == Kohive.OS.getCurrentHive().data.id) {
							controller
									.fireAction(
											'loadHive',
											controller,
											[Kohive.OS.getCurrentMemberships().data.items[0].data.hive_id]
									);
						};
					},
					failure	: function(errors) {
						// something has wrong so lets put the hive back to the way it was
						center.update(text);
						btn.removeClass('x-pending');

						Ext.Msg.alert(Ext.ux.Translator.translate((isPending)
										? 'decline_hive_invite'
										: 'leave_hive'), '302:'
										+ Ext.ux.Translator
												.translate('something_wrong'));
					}
				}
				);
			};
		};

		if (membership && abtn)
			return destroyFn('yes');

		// check if the hive is pending (cancel invite)
		if (isPending) {
			return Ext.Msg.show({
						title	: '',
						msg		: Ext.ux.Translator.translate(
								'decline_hive_invite_desc', {
									hive_title	: options.hive.title
								}
						),
						buttons	: {
							yes	: Ext.ux.Translator
									.translate('decline_hive_invite'),
							no	: Ext.ux.Translator.translate('cancel')
						},
						fn		: destroyFn
					});
		};

		// If it is an active hive, just destroy
		return Ext.Msg.show({
					title	: '',
					msg		: Ext.ux.Translator.translate('leave_hive_desc', {
								hive_title	: options.hive.title
							}),
					buttons	: {
						yes	: Ext.ux.Translator.translate('leave_hive'),
						no	: Ext.ux.Translator.translate('stay_in_hive')
					},
					fn		: destroyFn
				});
	}
	);

	/**
	 * Loads the Hive specified by the given Hive Id or Hive model
	 * Other UI elements should listen to either beforehiveload or hiveload to update
	 * themselves at the appropriate time.
	 * @param {Kohive.models.Hive/String} hive The Hive object to load, or a unique Hive ID
	 */
	this.registerAction('loadHive', function(id, button, animate) {
		// Kohive.OS.log('Stop pinging');
		// Kohive.OS.membersLoaded = false;
		// Kohive.OS.applicationsLoaded = false;

		var id = Math.abs(id) || null;
		var button = button || null;

		// Find the currently loaded hive, if one has been set
		var currentHive = os.getCurrentHive() || null;

		// If no hive is set then we must find one using the id
		var membership, hive;
		if (button) {
			membership = button.membership || null;
			hive = membership.data.hive || null;
		} else {
			// Loop through each of the hive memberships and find one with the correct hive id
			Ext.each(Kohive.OS.getCurrentMemberships().data.items, function(m) {
						if (id == m.data.hive.id) {
							membership = m;
							hive = membership.data.hive || null;
						};
					}, this);
		};

		// Now we have an instance of a hive model, we can go ahead and activate the hive
		if (membership && this.fireEvent('beforehiveload', membership)) {
			// Check if the user is trying to re-load the current hive
			if (currentHive && currentHive.data.hive.id == hive.id)
				return;

			// Toggle the hive
			if (button) {
				button.toggle();
			} else {
				try {
					Kohive.OS.getHivePanel().items.find(function(e) {
								if (e.hive.id == hive.id) {
									e.toggle();
								};
							});
				} catch (e) {
				};
			};

			// Add the history token
			var hash = window.location.hash;
			hash = hash.substring(1);
			hash = hash.split('/')[0];
			hash = Math.abs(hash);

			// Check if the current hash is the same as the new one
			if (hash != membership.data.hive.id) {
				Ext.History.add(membership.get('hive').id);
			};

			// Set the current hive to the newly loaded hive
			os.setCurrentHive(membership);

			var user = Kohive.OS.getCurrentUser();
			var controller = Kohive.OS.getController('users');
			if (user && controller
					&& user.get('default_hive_id') != membership.get('hive').id) {
				controller.update.defer(2000, controller, [user, {
									default_hive_id	: membership.get('hive').id
								}]);
			}
		};
	}
	);

	// load up the hives onLoad
	this.fireAction('refresh');
};
Ext.extend(Kohive.controllers.HivesController, ExtMVC.Controller, {
			/**
			 * 
			 * @param {Kohive.models.Membership} currentHive The current memberships
			 * @param {Kohive.models.Membership} newHive The new memberships
			 */
			checkForDifferences	: function(currentHive, newHive) {
				// Create an array for each of the memberships
				var currentHiveArray = [];
				var newHiveArray = [];

				// check if the length is different
				if (currentHive.data.items.length != newHive.data.items.length) {
					return true;
				};

				Ext.each(currentHive.data.items, function(item) {
							currentHiveArray.push(Ext.encode(item.data));
						}, this);

				Ext.each(newHive.data.items, function(item) {
							newHiveArray.push(Ext.encode(item.data));
						}, this);

				var different = false;

				Ext.each(currentHiveArray, function(item, index) {
							if (item != newHiveArray[index]) {
								return different = true;
							};
						}, this);

				return (different) ? true : false;
			},

			initListeners		: function() {
				this.on({
							scope				: this,
							'beforehiveload'	: this.onBeforeHiveLoad
						});
			},

			/**
			 * Called before the hive is loaded. Hides the application launcher and starts the hive loading.
			 */
			onBeforeHiveLoad	: function(controller, button) {
				// Kohive.OS.getApplicationLauncher().hideView();
				// this.fireAction('loadHive', this, [null, button, true]);
			}
		}
);

ExtMVC.OS.getOS().registerController('hives',
		Kohive.controllers.HivesController
);